<?php

interface Log
{
    public function write();
}

// 文件记录日志
class FileLog implements Log
{
    public function write(){
        echo 'file log write...';
    }
}

// 数据库记录日志
class DatabaseLog implements Log
{
    public function write(){
        echo 'database log write...';
    }
}

class User
{
    protected $log;
    public function __construct(Log $log)
    {
        $this->log = $log;
    }
    public function login()
    {
        // 登录成功，记录登录日志
        echo 'login success...';
        $this->log->write();
    }
}

class Ioc{

    protected $binding = [];

    public function bind($abstract,$concrete){
        $this->binding[$abstract]['concrete'] = function ($ioc) use($concrete) {
             return $ioc->build($concrete);
        };
    }

    public function make($abstract){
        return $this->binding[$abstract]['concrete']($this);
    }

    public function build($concrete){
        $reflector = new ReflectionClass($concrete);
        $constructor = $reflector->getConstructor();
        if(is_null($constructor)){
            return $reflector->newInstance();
        }else{
            $dependencies = $constructor->getParameters();
            $instances = $this->getDependencies($dependencies);
            return $reflector->newInstanceArgs($instances);
        }
    }

    protected function getDependencies($parameters){
        $dependencies = [];
        foreach ($parameters as $parameter){
            $dependencies[] = $this->make($parameter->getClass()->name);
        }
        return $dependencies;
    }
}

//实例化IoC容器
$ioc = new Ioc();
$ioc->bind('Log','FileLog');
$ioc->bind('user','User');
$user = $ioc->make('user');
$user->login();